package com.nanohadoop.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class Configuration {
    private static final Logger log = LoggerFactory.getLogger(Configuration.class);

    private static Configuration instance;
    private final Map<String, String> properties = new HashMap<>();
    
    // 默认配置
    private static final Map<String, String> DEFAULT_VALUES = new HashMap<>();
    static {
        // HDFS配置
        DEFAULT_VALUES.put("fs.defaultFS", "hdfs://localhost:9000");
        DEFAULT_VALUES.put("dfs.namenode.http.port", "50070");
        DEFAULT_VALUES.put("dfs.namenode.port", "9000");
        DEFAULT_VALUES.put("dfs.datanode.port", "50010");
        DEFAULT_VALUES.put("dfs.datanode.ipc.port", "50020");
        DEFAULT_VALUES.put("dfs.namenode.name.dir", "file:///tmp/dfs/name");
        DEFAULT_VALUES.put("dfs.datanode.data.dir", "file:///tmp/dfs/data");
        DEFAULT_VALUES.put("dfs.replication", "3");
        DEFAULT_VALUES.put("dfs.block.size", "67108864"); // 64MB

        // MapReduce配置
        DEFAULT_VALUES.put("mapreduce.framework.name", "local");
        DEFAULT_VALUES.put("mapreduce.jobtracker.port", "54311");
        DEFAULT_VALUES.put("mapreduce.tasktracker.port", "54312");
        DEFAULT_VALUES.put("mapreduce.shuffle.port", "13562");
        DEFAULT_VALUES.put("mapreduce.job.reduces", "1");
        DEFAULT_VALUES.put("mapreduce.task.io.sort.mb", "100");
        DEFAULT_VALUES.put("mapreduce.task.io.sort.factor", "10");
    }

    public Configuration() {
        loadDefaultConfiguration();
    }

    public static Configuration getInstance() {
        if (instance == null) {
            instance = new Configuration();
        }
        return instance;
    }

    public void loadConfigFile(String path) {
        try {
            File configFile = new File(path);
            if (!configFile.exists()) {
                log.error("配置文件不存在: " + path);
                return;
            }

            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document document = builder.parse(configFile);

            NodeList propertyList = document.getElementsByTagName("property");
            for (int i = 0; i < propertyList.getLength(); i++) {
                Element property = (Element) propertyList.item(i);
                String name = property.getElementsByTagName("n").item(0).getTextContent();
                String value = property.getElementsByTagName("value").item(0).getTextContent();
                properties.put(name, value);
            }
        } catch (Exception e) {
            log.error("加载配置文件失败: " + e.getMessage());
        }
    }

    private void loadDefaultConfiguration() {
        properties.putAll(DEFAULT_VALUES);
    }

    public String get(String name) {
        return properties.get(name);
    }

    public String get(String name, String defaultValue) {
        return properties.getOrDefault(name, defaultValue);
    }

    public int getInt(String name, int defaultValue) {
        String value = properties.get(name);
        if (value == null) {
            return defaultValue;
        }
        try {
            return Integer.parseInt(value);
        } catch (NumberFormatException e) {
            return defaultValue;
        }
    }

    public long getLong(String name, long defaultValue) {
        String value = properties.get(name);
        if (value == null) {
            return defaultValue;
        }
        try {
            return Long.parseLong(value);
        } catch (NumberFormatException e) {
            return defaultValue;
        }
    }

    public void set(String name, String value) {
        properties.put(name, value);
    }

    public Set<String> getKeys() {
        return properties.keySet();
    }
}
